package com.atguigu.yygh.hosp.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.yygh.hosp.globalexp.YyghException;
import com.atguigu.yygh.hosp.repository.HospitalRepository;
import com.atguigu.yygh.hosp.result.hosp.Result;
import com.atguigu.yygh.hosp.service.HospitalService;
import com.atguigu.yygh.hosp.service.HospitalSetService;
import com.atguigu.yygh.hosp.util.MD5;
import com.atguigu.yygh.model.hosp.BookingRule;
import com.atguigu.yygh.model.hosp.Hospital;
import com.atguigu.yygh.model.hosp.HospitalSet;
import com.atguigu.yygh.service.feign.DictFeignClient;
import com.atguigu.yygh.vo.hosp.HospitalQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;

import javax.swing.*;
import java.util.*;

@Service
public class HospitalServiceImpl implements HospitalService {

    @Autowired
    HospitalRepository hospitalRepository;

    @Autowired
    HospitalSetService hospitalSetService;
    @Autowired
    DictFeignClient dictFeignClient;

    /**
     *上传医院接口的需求
     *(医院端传过来的参数上传到mongodb中)
     *1.签名校验,校验成功,才可以上传,否则直接抛出异常
     *    医院端传递的一个参数sign(已经经过md5加密的签名)
     *    从尚医通平台的医院设置表中根据hoscode查询医院设置表中的signKey
     *    该值没有加密,在进行校验时,将医院设置表中的签名进行md5加密之后和医院端传递的签名进行比较即可
     *2.医院端传递的医院信息map,转成Hospital对象
     *3.为该医院的status赋予默认值,医院的上下线状态默认=1(已上线)
     *4.为医院端传递的logoData,将字符串中的所有空格替换成+
     *    logoData.replaceAll(" ","+");
     *5.判断该医院在mongdb中是否存在,如果不存在,直接添加(每个医院都有创建时间和最后修改时间)
     *   根据hoscode医院编号(唯一性)去mongodb中查询一下,如果没有查询到,说名不存在,执行添加操作
     *6.如果该医院存在,最终执行更新操作(根据主键更新,createTime字段保持不变,updateTime要更新)
     */
    @Override
    public void saveHospital(Map<String, Object> map) {
     //-----------------------------第一步--------------------------------------
        //医院端传递的签名(已加密的)
        Object sign = map.get("sign");
        if(StringUtils.isEmpty(sign)){
            throw new YyghException(20001,"医院端未传递签名");
        }

        //从医院设置表中查询该医院的签名,根据hoscode医院编号查询
        Object hoscode = map.get("hoscode");
        if(StringUtils.isEmpty(hoscode)){
            throw new YyghException(20001,"医院端未传递医院编号");
        }

        //根据医院编号查询医院设置
        HospitalSet hospitalSet = hospitalSetService.getByHoscode(hoscode);
        if(hospitalSet==null){
            throw new YyghException(20001,"为查询到该医院设置");
        }
        String signKey = hospitalSet.getSignKey();  //医院设置表中的签名(未加密)

        String encrypt = MD5.encrypt(signKey);
        if(!encrypt.equals(sign)){
            throw new YyghException(20001,"签名校验失败");
        }

        if(hospitalSet.getStatus()==0){
            throw new YyghException(20001,"医院设置已被锁定");
        }

    //----------------------------------第二步---------------------------------------
        /**
         * 将医院端传递的参数map,转换成Hospital对象
         * Hospital Hospital=new Hospital();
         * hospital.setHoscode(map.get("hoscode")+"");
         */
        String jsonString = JSON.toJSONString(map); //将map转换成json
        Hospital hospital = JSON.parseObject(jsonString, Hospital.class); //将json转换成java(Hospital.class)对象

    //-------------------------------第三步----------------------------------------------
        hospital.setStatus(1);
    //-------------------------------第四步-----------------------------------------------
        hospital.setLogoData(hospital.getLogoData().replaceAll(" ","+"));

    //-------------------------------第五步----------------------------------------------
        //判断该医院是否存在,根据hoscode去mongodb中查询
        Hospital hospitalFromMongo = hospitalRepository.findByHoscode(hospital.getHoscode());
        if(hospitalFromMongo==null){
            hospital.setCreateTime(new Date());
            hospital.setUpdateTime(new Date());
            hospitalRepository.insert(hospital);
        }else {
    //-------------------------------第六步---------------------------------------------------
            //该医院已经存在,执行更新操作
            hospital.setId(hospitalFromMongo.getId());
            hospital.setCreateTime(hospitalFromMongo.getCreateTime());
            hospital.setUpdateTime(new Date());
            hospitalRepository.save(hospital);
        }
    }

    @Override
    public Hospital show(Map<String, Object> map) {
        //1.签名校验(和第一个接口的校验方式一样) 省略
        //2.获取参数hoscode,从mongodb中根据hoscode查询医院对象
        Object hoscode = map.get("hoscode");
        if(hoscode==null){
            throw new YyghException(20001,"医院不存在");
        }
        Hospital hospital = hospitalRepository.findByHoscode(hoscode + "");
        //hoscode + "" 是为了将 hoscode 变量转换为字符串类型。
        return hospital;
    }

    @Override
    public Page<Hospital> selectPage(Integer pageNum, Integer pageSize, HospitalQueryVo hospitalQueryVo) {

        //前端可能的查询条件: 省+城市+医院名称(前端searchObj中的查询条件值)
        String provinceCode = hospitalQueryVo.getProvinceCode();  //省
        String cityCode = hospitalQueryVo.getCityCode();         //市
        String hosname = hospitalQueryVo.getHosname();         //医院名称关键词

        Integer status = hospitalQueryVo.getStatus();  //医院的状态

        String hostype = hospitalQueryVo.getHostype();  //医院类型
        String districtCode = hospitalQueryVo.getDistrictCode();//医院的区

        //需要模糊查询(不需要先判断是否为空) 将查询条件封装成pojo
        Hospital hospital=new Hospital();
        hospital.setProvinceCode(provinceCode);
        hospital.setCityCode(cityCode);
        hospital.setHosname(hosname);
        hospital.setStatus(status);
        hospital.setHostype(hostype);
        hospital.setDistrictCode(districtCode);

        //模糊查询匹配器(字符串包含)
        ExampleMatcher exampleMatcher=ExampleMatcher.matching()
                .withIgnoreCase(true)
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
        //Example对象需要两个参数 实体类对象+匹配器
        Example<Hospital> example=Example.of(hospital,exampleMatcher);
        //分页+排序
        Pageable pageable= PageRequest.of(pageNum-1,pageSize,Sort.Direction.DESC,"createTime");

        Page<Hospital> page = hospitalRepository.findAll(example, pageable);

        /**
         * 为每个医院对象,查询到对应的医院等级名称和省市区名称
         * 向Param中添加两个属性: hostypeString + fullAddress(省市区名称+address)
         * 在医院服务中,调用数据字典服务;具体通过feign接口
         */
        page.getContent().stream().forEach(hosp -> {
            this.packHospital(hosp);
        });

        return page;
    }

    /**
     * 医院的上线和下线  status:0-1
     * 需求:根据id查询到该医院,将status的值进行更新
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(String id, Integer status) {
        Optional<Hospital> byId = hospitalRepository.findById(id);
        Hospital hospital = byId.get();
        hospital.setStatus(status);
        hospital.setUpdateTime(new Date()); //最后修改时间
        hospitalRepository.save(hospital);
    }

    /**
     * 根据id查询医院详情 hospital+bookingRule
     * @param id
     * @return
     */
    @Override
    public Map getHospById(String id) {
        //根据医院id查询医院对象
        Hospital hospital = hospitalRepository.findById(id).get();
        //为param属性赋值
        this.packHospital(hospital);
        //封装一个map
        Map map=new HashMap();
        map.put("hospital",hospital);
        map.put("bookingRule",hospital.getBookingRule());
        hospital.setBookingRule(null);  //前端不需要从hospital中获取bookingRule
        return map;
    }

    /**
     * 根据医院名称进行模糊查询
     * @param hosname
     * @return
     */
    @Override
    public List<Hospital> findByHosname(String hosname) {
       // List<Hospital> list = hospitalRepository.findByHosnameLike(hosname);
        List<Hospital> list = hospitalRepository.findByHosnameLikeAndStatusEquals(hosname, 1);
        return list;
    }

    /**
     * 根据医院编号hoscode 查询hospital+BookingRule
     * @param hoscode
     * @return
     */
    @Override
    public Map showDetail(String hoscode) {
        Hospital hospital = hospitalRepository.findByHoscode(hoscode);

        this.packHospital(hospital);  //为param属性赋值
        BookingRule bookingRule = hospital.getBookingRule();
        Map map=new HashMap<>();
        map.put("hospital",hospital);
        map.put("bookingRule",bookingRule);

        hospital.setBookingRule(null); //前端不需要从hospital里面获取BookingRule所以设置成null

        return map;
    }

    private void packHospital(Hospital hosp) {
        String provinceCode1 = hosp.getProvinceCode();
        String cityCode1 = hosp.getCityCode();
        String districtCode = hosp.getDistrictCode();
        String hostype = hosp.getHostype();

        //根据value查询省市区的名字
        String provinceString = dictFeignClient.getName(provinceCode1);
        String clientString = dictFeignClient.getName(cityCode1);
        String districtString = dictFeignClient.getName(districtCode);

        //根据value+dictCode查询医院等级名称
        String hostypeString = dictFeignClient.getName(hostype, "Hostype");

        //省+市+区+地址
        String fullAddress = provinceString+clientString+districtString+ hosp.getAddress();

        hosp.getParam().put("hostypeString",hostypeString);
        hosp.getParam().put("fullAddress",fullAddress);
    }


}
